home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 February: Tool Chest / Dev.CD Feb 95 / Dev.CD Feb 95.toast / Sample Code / Snippets / Toolbox / SetIndString / SetIndString.c
Encoding:
Text File  |  1992-07-15  |  3.0 KB  |  108 lines  |  [TEXT/MACA]

  1.  
  2. Bob,
  3.  
  4. I have been reviewing your question on how to set the contents of STR# resources
  5. from your program.
  6.  
  7. As it turns out, there is no Toolbox call to do this, mostly because resources are
  8. not meant to store data which changes frequently.  I have a solution to your
  9. problem, but it comes with a warning: PLEASE DON'T CHANGE ANY OF YOUR APPLICATIONS
  10. RESOURCES WHILE RUNNING.  Doing so will make it impossible for your program to run
  11. off of a fileserver or locked volume.
  12.  
  13. That out of the way the format of an STR# resource is:
  14.  
  15. 2 bytes       number of strings
  16. -------------------------------
  17. 1 byte        length of 1st str
  18. (variable)    1st string data
  19. -------------------------------
  20. 1 byte        length of nth str
  21. (variable)    nth string data
  22. ...
  23. ...
  24.  
  25. Note that the indexes into the strings are not at set positions, but instead are
  26. relative to the lengths of the previous strings.
  27.  
  28. Finally, here's a C function, SetIndString() which takes the same parameters as
  29. GetIndString().  This call does the opposite, namely, it sets a particular STR#
  30. string to the passed in string:
  31.  
  32. -------------
  33.  
  34. OSErr SetIndString(StringPtr theStr,short resID,short strIndex)
  35. {
  36.    Handle theRes;               /* handle pointing to STR# resource */
  37.    short numStrings;            /* number of strings in STR# */
  38.    short ourString;             /* counter to index up to strIndex */
  39.    char *resStr;                /* string pointer to STR# string to replace */
  40.    long oldSize;                /* size of STR# resource before call */
  41.    long newSize;                /* size of STR# resource after call */
  42.    unsigned long offset;        /* resource offset to str to replace*/
  43.  
  44.    /* make sure index is in bounds */
  45.  
  46.    if (resID < 1)
  47.    return -1;
  48.  
  49.    /* make sure resource exists */
  50.  
  51.    theRes = GetResource('STR#',resID);
  52.    if (ResError()!=noErr)
  53.    return ResError();
  54.    if (!theRes || !(*theRes))
  55.    return resNotFound;
  56.  
  57.    HLock(theRes);
  58.    HNoPurge(theRes);
  59.  
  60.    /* get # of strings in STR# */
  61.  
  62.    BlockMove(*theRes,&numStrings,sizeof(short));
  63.    if (strIndex > numStrings)
  64.    return resNotFound;
  65.  
  66.    /* get a pointer to the string to replace */
  67.  
  68.    offset = sizeof(short);
  69.    resStr = (char *) *theRes + sizeof(short);
  70.    for (ourString=1; ourString<strIndex; ourString++) {
  71.    offset += 1+resStr[0];
  72.    resStr += 1+resStr[0];
  73.    }
  74.  
  75.    /* grow/shrink resource handle to make room for new string */
  76.  
  77.    oldSize = GetHandleSize(theRes);
  78.    newSize = oldSize - resStr[0] + theStr[0];
  79.    HUnlock(theRes);
  80.    SetHandleSize(theRes,newSize);
  81.    if (MemError()!=noErr) {
  82.    ReleaseResource(theRes);
  83.    return -1;
  84.    }
  85.    HLock(theRes);
  86.    resStr = *theRes + offset;
  87.  
  88.    /* move old data forward/backward to make room */
  89.  
  90.    BlockMove(resStr+resStr[0]+1, resStr+theStr[0]+1, oldSize-offset-resStr[0]-1
  91.  
  92.    /* move new data in */
  93.  
  94.    BlockMove(theStr,resStr,theStr[0]+1);
  95.  
  96.    /* write resource out */
  97.  
  98.    ChangedResource(theRes);
  99.    WriteResource(theRes);
  100.    HPurge(theRes);
  101.    ReleaseResource(theRes);
  102.  
  103.    return ResError();
  104. }
  105.  
  106. ----------
  107.  
  108.